﻿using System;
using Windows.System;
using Windows.UI.Core;

namespace SharpDepend.WinRT
{
    class KeyboardManager : IKeyboardManager
    {
        private IGuiTimer mTempTimer;

        public KeybordSupport KeybordSupport
        {
            get
            {
                return KeybordSupport.Both;
            }
        }

        public event KeyPressedHandler OnKeyPressed;

        internal void LazyInit()
        {
            mTempTimer = SharpDepend.Manager.GUITimerManager.CreateTimer();
            mTempTimer.Interval = new TimeSpan(0, 0, 0, 0, 100);
            mTempTimer.Tick += TempTimer_Tick;
            mTempTimer.Start();
        }

        private void TempTimer_Tick()
        {
            var coreWindow = CoreWindow.GetForCurrentThread();
            if (coreWindow != null)
            {
                coreWindow.CharacterReceived += KeyboardManager_CharacterReceived;
                mTempTimer.Stop();
                mTempTimer = null;
                GC.Collect(); // Just to remove null pointer.
            }
        }

        private void KeyboardManager_CharacterReceived(CoreWindow sender, CharacterReceivedEventArgs args)
        {
            var call = OnKeyPressed;
            if (call != null)
            {
                char c = Convert.ToChar(args.KeyCode);

                Key modifier = Key.None;

                if (sender.GetKeyState(VirtualKey.LeftControl) == CoreVirtualKeyStates.Down)
                {
                    modifier = Key.LeftCtrl;
                }
                else if (sender.GetKeyState(VirtualKey.RightControl) == CoreVirtualKeyStates.Down)
                {
                    modifier = Key.RightCtrl;
                }
                else if (sender.GetKeyState(VirtualKey.LeftMenu) == CoreVirtualKeyStates.Down)
                {
                    modifier = Key.LeftAlt;
                }
                else if (sender.GetKeyState(VirtualKey.RightMenu) == CoreVirtualKeyStates.Down)
                {
                    modifier = Key.RightAlt;
                }
                else if (sender.GetKeyState(VirtualKey.LeftShift) == CoreVirtualKeyStates.Down)
                {
                    modifier = Key.LeftShift;
                }
                else if (sender.GetKeyState(VirtualKey.RightShift) == CoreVirtualKeyStates.Down)
                {
                    modifier = Key.RightShift;
                }

                // Special.
                Key key = (Key)c;
                if (c == 8)
                {
                    key = Key.Back;
                }

                call(key, c, modifier);
            }
        }

        public bool IsKeyDown(Key key)
        {
            CoreWindow coreWindow = CoreWindow.GetForCurrentThread();

            switch (key)
            {
                case Key.None:
                    break;
                case Key.Cancel:
                    break;
                case Key.Back:
                    break;
                case Key.Tab:
                    break;
                case Key.LineFeed:
                    break;
                case Key.Clear:
                    break;
                case Key.Return:
                    //case Key.Enter:
                    break;
                case Key.Pause:
                    break;
                case Key.CapsLock:
                    //case Key.Capital:
                    break;
                case Key.HangulMode:
                    //case Key.KanaMode:
                    break;
                case Key.JunjaMode:
                    break;
                case Key.FinalMode:
                    break;
                case Key.KanjiMode:
                    //case Key.HanjaMode:
                    break;
                case Key.Escape:
                    break;
                case Key.ImeConvert:
                    break;
                case Key.ImeNonConvert:
                    break;
                case Key.ImeAccept:
                    break;
                case Key.ImeModeChange:
                    break;
                case Key.Space:
                    break;
                case Key.PageUp:
                    //case Key.Prior:
                    break;
                case Key.PageDown:
                    //case Key.Next:
                    break;
                case Key.End:
                    break;
                case Key.Home:
                    break;
                case Key.Left:
                    break;
                case Key.Up:
                    break;
                case Key.Right:
                    break;
                case Key.Down:
                    break;
                case Key.Select:
                    break;
                case Key.Print:
                    break;
                case Key.Execute:
                    break;
                case Key.Snapshot:
                    //case Key.PrintScreen:
                    break;
                case Key.Insert:
                    break;
                case Key.Delete:
                    break;
                case Key.Help:
                    break;
                case Key.D0:
                    break;
                case Key.D1:
                    break;
                case Key.D2:
                    break;
                case Key.D3:
                    break;
                case Key.D4:
                    break;
                case Key.D5:
                    break;
                case Key.D6:
                    break;
                case Key.D7:
                    break;
                case Key.D8:
                    break;
                case Key.D9:
                    break;
                case Key.A:
                    break;
                case Key.B:
                    break;
                case Key.C:
                    break;
                case Key.D:
                    break;
                case Key.E:
                    break;
                case Key.F:
                    break;
                case Key.G:
                    break;
                case Key.H:
                    break;
                case Key.I:
                    break;
                case Key.J:
                    break;
                case Key.K:
                    break;
                case Key.L:
                    break;
                case Key.M:
                    break;
                case Key.N:
                    break;
                case Key.O:
                    break;
                case Key.P:
                    break;
                case Key.Q:
                    break;
                case Key.R:
                    break;
                case Key.S:
                    break;
                case Key.T:
                    break;
                case Key.U:
                    break;
                case Key.V:
                    break;
                case Key.W:
                    break;
                case Key.X:
                    break;
                case Key.Y:
                    break;
                case Key.Z:
                    break;
                case Key.LWin:
                    break;
                case Key.RWin:
                    break;
                case Key.Apps:
                    break;
                case Key.Sleep:
                    break;
                case Key.NumPad0:
                    break;
                case Key.NumPad1:
                    break;
                case Key.NumPad2:
                    break;
                case Key.NumPad3:
                    break;
                case Key.NumPad4:
                    break;
                case Key.NumPad5:
                    break;
                case Key.NumPad6:
                    break;
                case Key.NumPad7:
                    break;
                case Key.NumPad8:
                    break;
                case Key.NumPad9:
                    break;
                case Key.Multiply:
                    break;
                case Key.Add:
                    break;
                case Key.Separator:
                    break;
                case Key.Subtract:
                    break;
                case Key.Decimal:
                    break;
                case Key.Divide:
                    break;
                case Key.F1:
                    break;
                case Key.F2:
                    break;
                case Key.F3:
                    break;
                case Key.F4:
                    break;
                case Key.F5:
                    break;
                case Key.F6:
                    break;
                case Key.F7:
                    break;
                case Key.F8:
                    break;
                case Key.F9:
                    break;
                case Key.F10:
                    break;
                case Key.F11:
                    break;
                case Key.F12:
                    break;
                case Key.F13:
                    break;
                case Key.F14:
                    break;
                case Key.F15:
                    break;
                case Key.F16:
                    break;
                case Key.F17:
                    break;
                case Key.F18:
                    break;
                case Key.F19:
                    break;
                case Key.F20:
                    break;
                case Key.F21:
                    break;
                case Key.F22:
                    break;
                case Key.F23:
                    break;
                case Key.F24:
                    break;
                case Key.NumLock:
                    break;
                case Key.Scroll:
                    break;
                case Key.LeftShift:
                    return Pressed(coreWindow, VirtualKey.LeftShift);
                case Key.RightShift:
                    return Pressed(coreWindow, VirtualKey.RightShift);
                case Key.LeftCtrl:
                    return Pressed(coreWindow, VirtualKey.LeftControl);
                case Key.RightCtrl:
                    return Pressed(coreWindow, VirtualKey.RightControl);
                case Key.LeftAlt:
                case Key.RightAlt:
                    return Pressed(coreWindow, VirtualKey.Menu);
                case Key.BrowserBack:
                    break;
                case Key.BrowserForward:
                    break;
                case Key.BrowserRefresh:
                    break;
                case Key.BrowserStop:
                    break;
                case Key.BrowserSearch:
                    break;
                case Key.BrowserFavorites:
                    break;
                case Key.BrowserHome:
                    break;
                case Key.VolumeMute:
                    break;
                case Key.VolumeDown:
                    break;
                case Key.VolumeUp:
                    break;
                case Key.MediaNextTrack:
                    break;
                case Key.MediaPreviousTrack:
                    break;
                case Key.MediaStop:
                    break;
                case Key.MediaPlayPause:
                    break;
                case Key.LaunchMail:
                    break;
                case Key.SelectMedia:
                    break;
                case Key.LaunchApplication1:
                    break;
                case Key.LaunchApplication2:
                    break;
                case Key.OemSemicolon:
                //case Key.Oem1:
                    break;
                case Key.OemPlus:
                    break;
                case Key.OemComma:
                    break;
                case Key.OemMinus:
                    break;
                case Key.OemPeriod:
                    break;
                case Key.OemQuestion:
                //case Key.Oem2:
                    break;
                case Key.OemTilde:
                //case Key.Oem3:
                    break;
                case Key.AbntC1:
                    break;
                case Key.AbntC2:
                    break;
                case Key.OemOpenBrackets:
                //case Key.Oem4:
                    break;
                case Key.OemPipe:
                //case Key.Oem5:
                    break;
                case Key.OemCloseBrackets:
                //case Key.Oem6:
                    break;
                case Key.OemQuotes:
                //case Key.Oem7:
                    break;
                case Key.Oem8:
                    break;
                case Key.OemBackslash:
                //case Key.Oem102:
                    break;
                case Key.ImeProcessed:
                    break;
                case Key.System:
                    break;
                case Key.OemAttn:
                //case Key.DbeAlphanumeric:
                    break;
                case Key.OemFinish:
                //case Key.DbeKatakana:
                    break;
                case Key.DbeHiragana:
                //case Key.OemCopy:
                    break;
                case Key.DbeSbcsChar:
                //case Key.OemAuto:
                    break;
                case Key.DbeDbcsChar:
                //case Key.OemEnlw:
                    break;
                case Key.OemBackTab:
                //case Key.DbeRoman:
                    break;
                case Key.DbeNoRoman:
                //case Key.Attn:
                    break;
                case Key.CrSel:
                //case Key.DbeEnterWordRegisterMode:
                    break;
                case Key.ExSel:
                //case Key.DbeEnterImeConfigureMode:
                    break;
                case Key.EraseEof:
                //case Key.DbeFlushString:
                    break;
                case Key.Play:
                //case Key.DbeCodeInput:
                    break;
                case Key.DbeNoCodeInput:
                //case Key.Zoom:
                    break;
                case Key.NoName:
                //case Key.DbeDetermineString:
                    break;
                case Key.DbeEnterDialogConversionMode:
                //case Key.Pa1:
                    break;
                case Key.OemClear:
                    break;
                case Key.DeadCharProcessed:
                    break;
                default:
                    break;
            }

            return false;
        }

        private static bool Pressed(CoreWindow coreWindow, VirtualKey key)
        {
            bool pressed = (coreWindow.GetKeyState(key) & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;

            return pressed;
        }
        
        public void ShowVirtualKeyboard(string titleHint, string descriptionHint, string defaultText, KeyboardTextChanged onTextChanged)
        {
            SharpDepend.Manager.DialogManager.Input(descriptionHint, titleHint, defaultText, delegate(bool success, string input, object parameter)
            {
                if (success)
                {
                    onTextChanged(input.Replace("\n\r", "\n").Replace("\r", "\n"));
                }
            }, null);
        }
    }
}
